package controlmercancias.remoto.servidortren;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import controlmercancias.configuracion.Configuracion;
import controlmercancias.configuracion.GestorConfiguracion;
import controlmercancias.datos.AccesoDatosBD;
import controlmercancias.datos.IAccesoDatos;
import controlmercancias.dominio.Tren;
import controlmercancias.dominio.Usuario;
import controlmercancias.gui.administracion.AdminServerGUI;
import controlmercancias.util.SocketManager;
import java.awt.Image;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

/**
 *
 * @author Hasier
 */
public class ServidorTrenDemon {

    private static List<String> trenesUsados = new ArrayList<String>();
    private static int maxConnections = 5;
    private static int numConexionesActivas = 0;
    private static IAccesoDatos ad;
    private static Properties p;
    private static Map<ServidorTren, Thread> usuarios = new HashMap<ServidorTren, Thread>();
    private static AdminListener admin;
    private static AdminServerGUI servergui;
    private static FileInputStream properties;
    public static final Image appIcon = new ImageIcon(ServidorTrenDemon.class.getResource("/controlmercancias/resources/icono.png")).getImage();

    public static void main(String[] args) {
        init();
        Runnable r = new Runnable() {

            @Override
            public void run() {
                try {
                    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                        if ("Nimbus".equals(info.getName())) {
                            UIManager.setLookAndFeel(info.getClassName());
                            break;
                        }
                    }
                } catch (Exception e) {
                }
                servergui = new AdminServerGUI();
                servergui.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
        try {
            ServerSocket ss = new ServerSocket(8089);
            System.out.println("Servidor de trenes activo y esperando...");
            for (;;) {
                Socket socket = ss.accept();
                if (numConexionesActivas < maxConnections) {
                    ServidorTren s = new ServidorTren(socket);
                    Thread t = new Thread(s);
                    t.start();
                } else {
                    SocketManager sm = new SocketManager(socket);
                    sm.write("499 Petición rechazada");
                    sm.close();
                }
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    public static void exit() {
        Thread.currentThread().interrupt();
        System.exit(0);
    }

    public static AdminServerGUI getServerGUI() {
        return servergui;
    }

    private static void init() {
        GestorConfiguracion.cargarConfiguracion("BD/configuracionBD.properties");
        AccesoDatosBD.inicializarParametrosConexion(Configuracion.getInstance());
        ad = new AccesoDatosBD();
        ad.init();
        p = new Properties();
        try {
            properties = new FileInputStream(new File("updateParameters/parameters.properties"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static IAccesoDatos getAccesoDatos() {
        return ad;
    }

    public static void setMaxConnections(int max) {
        maxConnections = max;
    }

    public static int getMaxConnections() {
        return maxConnections;
    }

    static void trainServerFinished(ServidorTren st) {
        usuarios.remove(st);
        numConexionesActivas--;
        st.setTren(null);
        refreshAdmin();
    }

    static void trainServerStarted(ServidorTren s, Thread t) {
        numConexionesActivas++;
        usuarios.put(s, t);
        refreshAdmin();
    }

    private static void refreshAdmin() {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                if (admin != null) {
                    admin.refresh();
                }
            }
        });
    }

    static String getUpdateConnectionIP() throws IOException {
        p.load(properties);
        return p.getProperty("ip");
    }

    static int getUpdateConnectionPort() throws IOException {
        p.load(properties);
        return Integer.parseInt(p.getProperty("port"));
    }

    public static void logInAdmin(AdminListener al) {
        admin = al;
    }

    public static void logOutAdmin() {
        admin = null;
    }

    public static List<ServidorTren> getConnectedUsers() {
        return new ArrayList<ServidorTren>(usuarios.keySet());
    }

    public static void expulsarUser(ServidorTren st) {
        try {
            st.forceExit();
        } catch (IOException ex) {
            ex.printStackTrace();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        trainServerFinished(st);
        try {
            usuarios.get(st).interrupt();
        } catch (Exception ex) {
        }
    }

    public static void deleteUser(Usuario u) {
        ad.deleteUsuario(u);
    }

    public static void addUser(Usuario u) {
        ad.addUsuario(u);
    }

    public static void setUser(Usuario u) {
        ad.setUsuario(u);
    }

    public static List<Tren> getAllTrenes() {
        return ad.getTrenes();
    }

    public static List<String> getUsedTrenes() {
        return trenesUsados;
    }

    public static boolean addTrenUsado(String tren) {
        if (trenesUsados.contains(tren)) {
            return false;
        }
        if (tren != null) {
            trenesUsados.add(tren);
        }
        return true;
    }

    public static void removeTrenUsado(String tren) {
        if (tren != null) {
            trenesUsados.remove(tren);
        }
    }
}
